
const FIRSTHEAD = 0xAA
const SECONDHEAD = 0x55

// <------------------------------------------下行包 ------------------------------------------>
//------------------ 血氧信息相关  -----------------
/** 发送血氧参数使能 */
const CRAP20DataTypeSendSpo2ParamEnable = 0X84
/** 发送血氧波形使能 */
const CRAP20DataTypeSendSpo2WaveEnable = 0X85
/** 血氧参数包 */
const CRAP20DataTypeGetSpo2ParamPackage = 0X01
/** 血氧波形包 */
const CRAP20DataTypeGetSpo2WavePackage = 0X02
/** 查询设备时间 */
const CRAP20DataTypeQueryForDeviceTime = 0X86
/** 设置设备时间 */
const CRAP20DataTypeSetForDeviceTime = 0X87
/** 查询记录列表 */
const CRAP20DataTypeQueryRecordsList = 0X8A
/** 设置血氧参数 */
const CRAP20DataTypeSetSpo2Param = 0X8C
/** 删除所有记录*/
const CRAP20DataTypeDeleteAllRecords = 0X8D
/** 查询血氧报警参数信息 */
const CRAP20DataTypeQueryForSpo2AlertParamInfo = 0X91
/** 设置血氧报警参数信息 */
const CRAP20DataTypeSetForSpo2AlertParamInfo = 0X92
//--------------- 设备信息相关  -----------------
/** 查询版本 */
const CRAP20DataTypeQueryForVersion = 0X81
/** 查询序列号 */
const CRAP20DataTypeQueryForSerialNumber = 0X82
/** 查询电池电量 */
const CRAP20DataTypeQueryForBatteryLevel = 0X83
/** 查询背光等级 */
const CRAP20DataTypeQueryForBackgroundLightLevel = 0X84
/** 设置背光等级 */
const CRAP20DataTypeSetForBackgroundLightLevel = 0X85
/** 查询客户定制信息 */
const CRAP20DataTypeQueryForCustomizedInformation = 0X86
/** 查询蓝牙MAC地址(pc-60f可用) */
const CRAP20DataTypeQueryForMACAddress = 0XA1

//-----------------  鼻息流相关  -----------------
/** 鼻息流波形包 */
const CRAP20DataTypeGetNasalFlowWavePackage = 0X01
/** 鼻息流参数 */
const CRAP20DataTypeGetNasalFlowParam = 0X02
/** 发送鼻息流波形包使能设置 */
const CRAP20DataTypeSendNasalFlowWavePackageEnable = 0X83
/** 发送鼻息流参数包使能设置 */
const CRAP20DataTypeSendNasalFlowParamEnable = 0X84
//-----------------  三轴加速度相关  -----------------
/** 发送三轴加速度波形包使能设置 */
const CRAP20DataTypeSendThree_AxisWavePackageEnable = 0X81
/** 三轴加速度波形包 */
const CRAP20DataTypeGetThree_AxiswWavePackage = 0X02
// -----------------  用户ID相关  -----------------
/** 查询用户ID */
const CRAP20DataTypeQueryForUserID = 0X81
/** 设置用户ID */
const CRAP20DataTypeSetForUserID = 0X82
// -----------------  无效  -----------------
const CRAP20DataTypeInvalied = 0x00

// <------------------------------------------上行包 ------------------------------------------>
//----------------- 血氧信息相关  -----------------
/** 版本信息 */
const CRAP20ResponceDataTypeQueryForTwoBitVersion = 0X03
/** 发送血氧参数使能 */
const CRAP20ResponceDataTypeSendSpo2ParamEnable = 0X04
/** 发送血氧波形使能 */
const CRAP20ResponceDataTypeSendSpo2WaveEnable = 0X05
/** 血氧参数包 */
const CRAP20ResponceDataTypeGetSpo2ParamPackage = 0X01
/** 血氧波形包 */
const CRAP20ResponceDataTypeGetSpo2WavePackage = 0X02
/** 查询设备时间 */
const CRAP20ResponceDataTypeQueryForDeviceTime = 0X06
/** 设置设备时间 */
const CRAP20ResponceDataTypeSetForDeviceTime = 0X07
/** 查询记录列表 */
const CRAP20ResponceDataTypeQueryRecordsList = 0X0A
/** 获取指定记录 */
const CRAP20ResponceDataTypeGetRecord = 0X0B
/** 设置血氧参数 */
const CRAP20ResponceDataTypeSetSpo2Param = 0X0C
/** 删除所有记录 */
const CRAP20ResponceDataTypeDeleteAllRecords = 0X0D
/** 查询血氧报警参数信息 */
const CRAP20ResponceDataTypeQueryForSpo2AlertParamInfo = 0X11
/** 设置血氧报警参数信息 */
const CRAP20ResponceDataTypeSetForSpo2AlertParamInfo = 0X12
/** 设置血氧报警参数信息 */
const CRAP20ResponceDataTypeSetForWorkStatusData = 0x21

//-----------------设备信息相关  -----------------
/** 查询版本 */
const CRAP20ResponceDataTypeQueryForFourBitVersion = 0X01
/** 查询序列号 */
const CRAP20ResponceDataTypeQueryForSerialNumber = 0X02
/** 查询电池电量 */
const CRAP20ResponceDataTypeQueryForBatteryLevel = 0X03
/** 查询背光等级 */
const CRAP20ResponceDataTypeQueryForBackgroundLightLevel = 0X04
/** 设置背光等级 */
const CRAP20ResponceDataTypeSetForBackgroundLightLevel = 0X05
/** 查询客户定制信息 */
const CRAP20ResponceDataTypeQueryForCustomizedInformation = 0X06
/** 查询蓝牙MAC地址(pc-60f可用) */
const CRAP20ResponceDataTypeQueryForMACAddress = 0X21

//----------------- 鼻息流相关  -----------------
/** 鼻息流波形包 */
const CRAP20ResponceDataTypeGetNasalFlowWavePackage = 0X01
/** 鼻息流参数 */
const CRAP20ResponceDataTypeGetNasalFlowParam = 0X02
/** 发送鼻息流波形包使能设置 */
const CRAP20ResponceDataTypeSendNasalFlowWavePackageEnable = 0X03
/** 发送鼻息流参数包使能设置 */
const CRAP20ResponceDataTypeSendNasalFlowParamEnable = 0X04
//-----------------  三轴加速度相关  -----------------
/** 发送三轴加速度波形包使能设置 */
const CRAP20ResponceDataTypeSendThree_AxisWavePackageEnable = 0X01
/** 三轴加速度波形包 */
const CRAP20ResponceDataTypeGetThree_AxiswWavePackage = 0X02
//-----------------  用户ID相关  -----------------
/** 查询用户ID */
const CRAP20ResponceDataTypeQueryForUserID = 0X01
/** 设置用户ID */
const CRAP20ResponceDataTypeSetForUserID = 0X02
//----------------- 发送温度包相关  -----------------
/** 获取温度包 */
const CRAP20ResponceDataTypeGetTempPackage = 0x01
// -----------------  无效  -----------------
const CRAP20ResponceDataTypeInvalied = 0x00

// <------------------------------------------令牌 ------------------------------------------>
const CRAP20TokenSpo2Related = 0x0F
const CRAP20TokenDeviceInfoRelated = 0xF0
const CRAP20TokenNasalFlowRelated = 0x2D
const CRAP20TokenThree_AxisRelated = 0x5A
const CRAP20TokenUserIDRelated = 0xE1
const CRAP20TokenTemparaturePackage = 0x3C
//-----------------  无效  -----------------
const CRAP20TokenInvalied = 0x00
const tool = require('../FunctionTool.js')



function setDelegate(delegate)
{
	this.delegate = delegate
	this.data =
		{
			commands: [],
		  analyzingDatas: [],//缓存数据
			recordsListCounts: [],
			recordsInfos: [],
		}
	
	this.delegate.GetSpo2Wave = delegate['GetSpo2Wave']
	this.delegate.GetSpo2Param = delegate['GetSpo2Param']
	this.delegate.GetWorkStatusData = delegate['GetWorkStatusData']
	this.delegate.GetFourBitsDeviceInfo = delegate['GetFourBitsDeviceInfo']
	this.delegate.GetDeviceBatteryLevel = delegate['GetDeviceBatteryLevel']


	//根据设备ID获取缓存数据
	this.getAnalyzingData = (deviceID) =>
	{
		for (var i = 0 ;i < this.data.analyzingDatas.length ;i++)
		{
			if (this.data.analyzingDatas[i]['device'].deviceID == deviceID)
				return this.data.analyzingDatas[i]['dataArray']
		}
		return null
	}
	//根据设备ID获取命令数组
	this.getCommandsArray = (deviceID) =>
 {
		for (var i = 0; i < this.data.commands.length; i++)
	 {
			if (this.data.commands[i]['device'].deviceID == deviceID)
				return this.data.commands[i]['dataArray']
		}
		return null
	}


	/** 分析数据 */
	this.analyzeNumberArray = (numberArray, device) =>
	{
		//1.包小于5，包不完整,不解包
		if (numberArray.length < 5)
			return;
		//2.找包头
		var packageHeads = []
		for (var i = 0; i < numberArray.length;i++)
		{
			//如果有 AA 55 ,则存在包头
			if (numberArray[i] == 0xAA && numberArray[i + 1] == 0x55)
			 {
				 packageHeads[packageHeads.length] = i
			 }
		}
		//3.判断包头是否存在,如果没有包头
		if (packageHeads.length == 0)
			return;
		//4.丢弃第一个包头之前的全部数据,保证每个数据包都有包头
		numberArray.splice(0,packageHeads[0])
		//5.检查包头
		this.checkPackageHead(packageHeads,device)
		//6.执行命令
		var commandsArray = this.getCommandsArray(device.deviceID)
		for (var i = 0 ; i < commandsArray.length; i++)
		{
			this.executCommand(device,commandsArray[i])
		}
		//7.清除命令
		commandsArray.splice(0)
	}

	/** 检查包头 */
	this.checkPackageHead = (packageHeads,device) =>
	{
		const array = this.getAnalyzingData(device.deviceID)
		//获取命令数组
		var commandsArray = this.getCommandsArray(device.deviceID)
		//1.判断包头的个数，检查整个缓存数据
		if (packageHeads.length == 1)
		{
			//用数组获取一个命令
			let command = this.getCommand(array, device)
			//如果获取成功，则保留命令，并将这段数据清除。如果获取失败，不处理
			if (command)
			{
				//保存命令
				commandsArray[commandsArray.length] = command
				//清除这段数据
				array.splice(0)
			}
			return
		}
	 //2. 缓存数据有多个包头
		for (var i = 0 ; i < packageHeads.length ;i++)
		{
			//根据包头分解出子数组
			//分情况处理，不是最后一个包头的情况下
			if (i != (packageHeads.length - 1))
			{
				var subArray = array.slice(0, packageHeads[i + 1])
				let command = this.getCommand(subArray, device)
				//保存命令
				if (command)
					commandsArray[commandsArray.length] = command
				//清除这段数据
				array.splice(0, packageHeads[i + 1])
				continue
			}
			//最后一个包的情况下，获取失败可能是因为包不完整，不能丢弃
			let command = this.getCommand(array, device)
			if (command)
		  {
				//保存命令
				commandsArray[commandsArray.length] = command
				//清除这段数据
				array.splice(0)
			}
		}
	}
	/** 根据给定一数组，获取一条完整的命令 */
	this.getCommand = (numberArray,device) =>
	{
		//逐项检查
		let flag = this.checkCommand(numberArray,device)
		if (flag)
		{
			var command =
				{
					"FirstHead": numberArray[0],
					"Second": numberArray[1],
					"Token": numberArray[2],
					"Length": numberArray[3],
					"DataType": numberArray[4],
					"Content": numberArray.slice(4),
					"CRC": numberArray[numberArray.length - 1]
				}
			return command
		}
		return null
	}
	/** 验证一数组，判断是否为一条完整的命令 */
	this.checkCommand = (numberArray, device) =>
	{
		//验证长度
		if (this.checkCommandLength(numberArray,device) == false)
			return false
		//验证 token  略
		//验证 dataType  略
		//验证CRC
		if (this.checkCommandCRC(numberArray,device) == false)
			return false
		return true
	}
	/** 判断长度是否正确 */
	this.checkCommandLength = (numberArray, device) =>
	{
		let length = numberArray.length
		let commandLength = numberArray[3]
		if (length >= (commandLength + 4))
			return true
		return false
	}
	/** 判断长度是否正确 */
	this.checkCommandCRC = (numberArray, device) =>
	 {
		let arrayCRC = numberArray[numberArray.length - 1]
		let commandCRC = tool.getCRCWithArray(numberArray)
		if (arrayCRC = commandCRC)
			return true
		return false
	}
	/** 为一个设备执行一条命令 */
	this.executCommand = (device,command) =>
	{
		//1.分token执行
		switch (command.Token)
		{
			case CRAP20TokenSpo2Related :
				this.executSpo2RelatedCommand(device,command)
				break;
			case CRAP20TokenDeviceInfoRelated:
				this.analyzeForDeviceInfoRelatedData(device, command)
				break;

		}
	}
	/** 执行血氧相关token命令 */
	this.executSpo2RelatedCommand = (device, command) =>
	{

		//1.分dataType执行
		switch (command.DataType)
		{
			case CRAP20ResponceDataTypeQueryForTwoBitVersion:
				this.getDeviceTwoBitsInfoResponce(device, command)
 				break;

			case CRAP20ResponceDataTypeSendSpo2ParamEnable:

				break;

			case CRAP20ResponceDataTypeSendSpo2WaveEnable:
				this.getSpo2ParamResponce(device,command)
				break;

			case CRAP20ResponceDataTypeGetSpo2ParamPackage:
				this.analyzeSpo2ParamCommand(device, command)
				break;

			case CRAP20ResponceDataTypeGetSpo2WavePackage:
				this.analyzeSpo2WaveCommand(device, command)
				break;

			case CRAP20ResponceDataTypeQueryForDeviceTime:

				break;

			case CRAP20ResponceDataTypeSetForDeviceTime:

				break;

			case CRAP20ResponceDataTypeQueryRecordsList:

				break;

			case CRAP20ResponceDataTypeGetRecord:

				break;

			case CRAP20ResponceDataTypeSetSpo2Param:

				break;

			case CRAP20ResponceDataTypeDeleteAllRecords:

				break;

			case CRAP20ResponceDataTypeQueryForSpo2AlertParamInfo:

				break;

			case CRAP20ResponceDataTypeSetForSpo2AlertParamInfo:

				break;

			case CRAP20ResponceDataTypeSetForWorkStatusData:
				this.analyzeWorkStatusData(device, command)
				break;
		}

	}

	this.analyzeForDeviceInfoRelatedData = (device,command) =>
	{

		switch (command.DataType)
    {
        case CRAP20ResponceDataTypeQueryForFourBitVersion:    /** 查询版本 */
						this.getDeviceFourBitsInfoResponce(device,command)
            break;
        case CRAP20ResponceDataTypeQueryForSerialNumber:    /** 查询序列号 */

             break;
        case CRAP20ResponceDataTypeQueryForBatteryLevel:    /** 查询电池电量 */

            break;
        case CRAP20ResponceDataTypeQueryForBackgroundLightLevel:    /** 查询背光等级 */

            break;
        case CRAP20ResponceDataTypeSetForBackgroundLightLevel:    /** 设置背光等级 */

            break;
        case CRAP20ResponceDataTypeQueryForCustomizedInformation:    /** 查询客户定制信息 */

            break;
        case CRAP20ResponceDataTypeQueryForMACAddress:    /** 查询蓝牙MAC地址 */

            break;

        default:
            break;
    }

	}

	//解析血氧波形
	this.analyzeSpo2WaveCommand = (device,command) =>
	{
		if(command.Content.length < 7)
		{
		}
		var waveData = []
		for (var i = 0; i < 5; i++)
		{
			//波形取第1-7位
			let waveValue = command.Content[i + 1] & 0x7f;
			//心跳搏动标记 取第0位
			let	pulse = command.Content[i + 1] & 0x80;
			waveData[i] = { "waveValue": waveValue,"pulse":pulse}

		}
		if (this.delegate.GetSpo2Wave)
			this.delegate.GetSpo2Wave(waveData, waveData.length,device)
 	}
	//解析血氧参数
	this.analyzeSpo2ParamCommand = (device, command) =>
	{
		let spo2Value = command.Content[1]
		let prValue = command.Content[2] + command.Content[3] * 256
		let piValue = command.Content[4]
		let battaryLevel = command.Content[6] & 0x1f;
    if (battaryLevel == 0)
        battaryLevel = (command.Content[6] & 0xC0) >>6;
		else //不超过4
        battaryLevel = (battaryLevel >>3) >= 4?3:(battaryLevel >>3)
	 	if (this.delegate.GetSpo2Param)
			this.delegate.GetSpo2Param(spo2Value, prValue, piValue, 0, 0, device)
		if (this.delegate.GetDeviceBatteryLevel)
			this.delegate.GetDeviceBatteryLevel(battaryLevel, device)

	}
	//解析血氧参数
	this.getSpo2ParamResponce = (device, command) =>
	{
		// console.log("血氧参数发送成功")
		// let spo2Value = command.Content[1]
		// let prValue = command.Content[2] + command.Content[3] * 256
		// let piValue = command.Content[4]
		// this.delegate.GetSpo2Param(device, spo2Value, prValue, piValue, false)
	}
	//解析设备信息(四位版本)
	this.getDeviceFourBitsInfoResponce = (device, command) =>
	{
		if (this.delegate.GetFourBitsDeviceInfo == null) return
		//第一个软件版本号字节
		let sv1H = command.Content[1] >> 4;
		let sv1L = command.Content[1] & 0x0f;
		//第二个软件版本号字节
		let sv2H = command.Content[2] >> 4;
		let sv2L = command.Content[2] & 0x0f;
		//第一个硬件版本号字节
		let hvH = command.Content[3] >>4
		let hvL = command.Content[3] & 0x0f;
		let softWareV = '' + sv1H+ '.' + sv1L + '.' + sv2H + '.' + sv2L
		let hardWareV = '' + hvH + '.' + hvL
		this.delegate.GetFourBitsDeviceInfo(softWareV, hardWareV, 0, 0, device)
	}

	//解析设备信息(两位版本)
	this.getDeviceTwoBitsInfoResponce = (device, command) =>
	{

		if (this.delegate.GetTwoBitsDeviceInfo == null) return
		let softVersion = '' + ((command.Content[1] & 0xf0) >> 4) + '.' + (command.Content[1]& 0x0f)
		let hardVersion = '' + ((command.Content[2] & 0xf0) >> 4) + '.' + (command.Content[2] & 0x0f)
		this.delegate.GetTwoBitsDeviceInfo(softVersion, hardVersion, 0, 0, device)
	}


	this.analyzeWorkStatusData = (device,command) =>
 {
		let mode = command.Content[1];
		let stage = command.Content[2];
		let para1 = command.Content[3];
		let para2 = command.Content[4];
		if (this.delegate.GetWorkStatusData)
			this.delegate.GetWorkStatusData(mode, stage, para1, para2, device)
 }

}

//前期处理
function didConnectDevice(device)
{
	let key = device.deviceID
	this.data.analyzingDatas[this.data.analyzingDatas.length] = {"device":device,"dataArray":[]}
	this.data.commands[this.data.commands.length] = { "device": device, "dataArray": []}
	this.data.recordsListCounts[this.data.recordsListCounts.length] = { "device": device, "dataArray": []}
	this.data.recordsInfos[this.data.recordsInfos.length] = { "device": device, "dataArray": [] }
}
//后期处理
function willDisconnect(device)
{
	if(device == null)
		return
	let key = device.deviceID
	deleteBufferArrayForDeviceID(key,this.data.analyzingDatas)
	deleteBufferArrayForDeviceID(key,this.data.commands)
	deleteBufferArrayForDeviceID(key,this.data.recordsListCounts)
	deleteBufferArrayForDeviceID(key,this.data.recordsInfos)
}

function deleteBufferArrayForDeviceID(deviceID,bufferArray)
{
	for (var i = 0; i < bufferArray.length; i++)
	{
		if (bufferArray[i].device.deviceID == deviceID)
			bufferArray.splice(i,1)
	}
}


//添加数据
function appendingNewData(numberArray, device)
{
	var array = this.getAnalyzingData(device.deviceID)
	let arrayLen = array.length
	for (var i = 0; i < numberArray.length; i++)
	{
		array[arrayLen + i] = numberArray[i]
	}
	//分析数据
	this.analyzeNumberArray(array,device)
}




/**  ---------------------------------------命令函数 */

//血氧波形使能
function spo2WaveEnable(device,enable)
{
	var crc = 0x00
	var length = 0x03
	var flag = 0
	if (enable)
	flag = 0x01
	var command = [FIRSTHEAD, SECONDHEAD, CRAP20TokenSpo2Related, length, CRAP20DataTypeSendSpo2WaveEnable, flag, crc]
	command[6] = tool.getCRCWithArray(command)
	device.writeValue(command)
}
//血氧参数使能
function spo2ParamEnable(device, enable)
{
	var crc = 0x00
	var length = 0x03
	var flag = 0
	if (enable)
		flag = 0x01
	var command = [FIRSTHEAD, SECONDHEAD, CRAP20TokenSpo2Related, length, CRAP20DataTypeSendSpo2ParamEnable, flag, crc]
	command[6] = tool.getCRCWithArray(command)
	device.writeValue(command)
}

//获取设备信息
function queryForDeviceVerisionInfomationFromDevice(device)
{
	queryDeviceInfoForTwoBits(device)
	queryDeviceInfoForFourBits(device)
}
function queryDeviceInfoForTwoBits(device)
{
	var crc = 0x00;
	var commandLength = 0x02;
	var commandByte = [FIRSTHEAD, SECONDHEAD, CRAP20TokenSpo2Related, commandLength, CRAP20DataTypeQueryForBatteryLevel, crc ]
	commandByte[5] = tool.getCRCWithArray(commandByte)
	device.writeValue(commandByte)
}
function  queryDeviceInfoForFourBits(device)
{
	var crc = 0x00;
	var commandLength = 0x02;
	var commandByte = [FIRSTHEAD, SECONDHEAD, CRAP20TokenDeviceInfoRelated, commandLength, CRAP20DataTypeQueryForVersion, crc ]
	commandByte[5] = tool.getCRCWithArray(commandByte)
	device.writeValue(commandByte)

}

module.exports.spo2WaveEnable = spo2WaveEnable;
module.exports.spo2ParamEnable = spo2ParamEnable;

module.exports.setDelegate = setDelegate;
module.exports.didConnectDevice = didConnectDevice;
module.exports.appendingNewData = appendingNewData;
module.exports.willDisconnect = willDisconnect;
module.exports.queryForDeviceVerisionInfomationFromDevice = queryForDeviceVerisionInfomationFromDevice;


